﻿using System;
using System.Runtime.InteropServices;

/**
*@file       netlib.cs
*@brief      common definition of net libray
*
*@author     graywind
*@version    1.0.0.1
*@data       2012/03/18
*/

/// <summary>
/// Summary description for Class1
/// </summary>
public class NetLib
{
#if DEBUG
    const string LIB_NAME = "pnnetlib_d.dll";
#else
    const string LIB_NAME = "pnnetlib.dll";
#endif

    /// <summary>
    /// usage types
    /// </summary>
    public enum eUsageType
    {
        Usage_Invalid = 0, //invalid, means not used
        Usage_Connect = 1, //this session connected with server
        Usage_Listen  = 2,  //this session connected with client
    }

    //value of invalid handle
    public const int INVALID_SESSION = -1;

    #region service relative
    /// <summary>
    /// create service
    /// </summary>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void create_service();

    /// <summary>
    /// destroy service
    /// </summary>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void destroy_service();

    /// <summary>
    /// whether initialize service
    /// </summary>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern bool is_service_init();

    /// <summary>
    /// initialize service
    /// </summary>
    /// <param name="thread_num">how many threads be used</param>
    /// <param name="max_listen">max count of sessions that can be accepted</param>
    /// <param name="max_connect">how many sessions can be connected to a server</param>
    /// <param name="buffer_length">bytes length of  the buffer used in the sesion</param>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void initialize_service(Int32 thread_num, Int32 max_session, Int32 buffer_length);

    /// <summary>
    /// start the service
    /// </summary>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void start_service();

    /// <summary>
    /// shut down the service
    /// </summary>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void terminate_service();
    #endregion

    #region actions
    /// <summary>
    /// start acceptor
    /// </summary>
    /// <param name="port">port to be used with this server</param>
    /// <param name="msgProc">callback function</param>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern bool start_listen(UInt16 port, NetCommon.MsgProc msgProc);

    /// <summary>
    /// disconnect a session
    /// </summary>
    /// <param name="session_index">index of session</param>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void close_session(Int32 session_handle);
    /// <summary>
    /// disable acceptor
    /// </summary>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void close_listen();

    /// <summary>
    /// broadcast a message to all live sessions
    /// </summary>
    /// <param name="msg_id">message identififier</param>
    /// <param name="msg_len">bytes length of message</param>
    /// <param name="msg_buffer">buffer of the content</param>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern int  broadcast_msg(UInt32 msg_id, UInt32 msg_len, IntPtr msg_buffer, eUsageType type);

    public static int broadcast_msg(UInt32 msg_id, eUsageType type)
    {
        return broadcast_msg(msg_id, 0, IntPtr.Zero, type);
    }

    /// <summary>
    /// max count of connection
    /// </summary>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern int  max_session();

    /// <summary>
    /// how many clients connected with this server
    /// </summary>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern int  cur_listen();

    /// <summary>
    /// how many server connected with this client
    /// </summary>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern int cur_connect();

    /// <summary>
    /// whether this session is alive
    /// </summary>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern bool is_alive(Int32 session_handle);

    /// <summary>
    /// create a connection
    /// </summary>
    /// <param name="ip">ip address of the server</param>
    /// <param name="port">port of the server</param>
    /// <param name="msgProc">callback function</param>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern int start_connect([MarshalAs(UnmanagedType.LPStr)]String ip, UInt16 port, NetCommon.MsgProc msgProc);

    /// <summary>
    /// send a message to the server from a connection
    /// </summary>
    /// <param name="handle">identifier of the connection which used to send message</param>
    /// <param name="msg_id">message identifier</param>
    /// <param name="msg_len">bytes length of message</param>
    /// <param name="msg_buffer">buffer of content</param>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern bool send_msg(Int32 session_handle, UInt32 msg_id, UInt32 msg_len, IntPtr msg_buffer);

    public static bool send_msg(Int32 session_handle, UInt32 msg_id)
    {
        return send_msg(session_handle, msg_id, 0, IntPtr.Zero);
    }

    /// <summary>
    /// close all connections
    /// </summary>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void close_all_connect();

    /// <summary>
    /// whether this session is alive
    /// </summary>
    /// <param name="handle"></param>
    /// <returns></returns>
    [DllImport(LIB_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern eUsageType get_usage(Int32 session_handle);
    #endregion
}
